#pragma once
#include <sys/time.h>
#include <sys/resource.h>
#include "../common/common.hpp"
#include "../common/log.hpp"

namespace wjh_run
{
    using namespace wjh_util;

    class runner
    {
    public:
        static void SetHardLimit(int cpuLimit, int memLimit)
        {
            struct rlimit cpu;
            cpu.rlim_cur = cpuLimit;
            cpu.rlim_max = RLIM_INFINITY;
            setrlimit(RLIMIT_CPU, &cpu);

            struct rlimit memory;
            memory.rlim_cur = memLimit * 1024; //以KB为单位
            memory.rlim_max = RLIM_INFINITY;
            setrlimit(RLIMIT_AS, &memory);
        }

        static int Run(std::string FileName, int cpuLimit, int memLimit)
        {
            //编译后的文件调用运行，接受文件运行时所报的错误
            pid_t id = fork();
            
            if(id < 0) return -1;
            else if(id == 0)
            {
                //子进程
                umask(0);
                int _stdin = open(Util::stdIn(FileName).c_str(), O_CREAT|O_RDONLY, 0444);
                int _stdout = open(Util::stdOut(FileName).c_str(), O_CREAT|O_WRONLY, 0644);
                int _stderr = open(Util::stdErr(FileName).c_str(), O_CREAT|O_WRONLY, 0644);
                
                //重定向标准输入、输出、错误
                dup2(_stdin, 0);
                dup2(_stdout, 1);
                dup2(_stderr, 2);

                //设置CPU和Memory限制
                SetHardLimit(cpuLimit, memLimit);
                //../temp/FileName -std=c++11
                execl(Util::run(FileName).c_str(), Util::run(FileName).c_str(), "-std=c++11", nullptr);

                logMessage(ERROR, "%s文件中第%d行, %s", __FILE__, __LINE__, "运行失败\n");
                //调用失败
                exit(1);
            }
            else
            {
                //父进程
                int status = 0;
                waitpid(id, &status, 0);
                if(status == 0) logMessage(NORMAL, "%s文件中第%d行, %s", __FILE__, __LINE__, "运行成功\n");
                return status & 0x7f;
            }
        }
    };
}